package de.sendorian.app.forumArchive.domain;


import static org.apache.commons.lang.StringUtils.*;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Transient;

import org.apache.commons.lang.StringUtils;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;

import de.sendorian.app.forumArchive.Config;

@Configurable
@Entity
public class Topic implements Cloneable {

	public static enum Type {
		ANNOUNCEMENT("Announcement"), STICKY_TOPIC("Sticky Topic"), HOT_TOPIC("Hot Topic"),
		CLOSED_TOPIC("Closed Topic"), TOPIC("Topic");

		private String detail;

		Type(String detail) {
			this.detail = detail;
		}

		public String getDetail() {
			return detail;
		}

		public static Type valueOfDetail(String typeString) {
			for (Type type : values()) {
				if (containsIgnoreCase(trim(typeString), type.detail)) {
					return type;
				}
			}
			return null;
		}
	}

	@Id
	@GeneratedValue
	private int id;

	private String url = "";

	private String name;

	@Enumerated(EnumType.STRING)
	private Type type;

	private Date lastPost;

	@ManyToOne
	private User topicStarter;

	@OneToMany(cascade = CascadeType.ALL)
	@Cascade(value = org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
	@Fetch(FetchMode.SUBSELECT)
	private List<Post> posts = new ArrayList<Post>();

	@Transient @Autowired
	Config config;
	

	public int getId() {
		return id;
	}


	public String getUrl() {
		return config.getBaseUrl() + url;
	}


	public void setUrl(String url) {
		this.url = url;
	}


	public String getName() {
		return name;
	}


	public void setName(String name) {
		name = name.replace("/", ",").replace("\\", ",");
		this.name = name;
	}


	public Type getType() {
		return type;
	}


	public void setType(Type type) {
		this.type = type;
	}


	public Date getLastPost() {
		return lastPost;
	}


	public void setLastPost(Date lastPost) {
		this.lastPost = lastPost;
	}


	public User getTopicStarter() {
		return topicStarter;
	}


	public void setTopicStarter(User topicStarter) {
		this.topicStarter = topicStarter;
	}


	public List<Post> getPosts() {
		return posts;
	}


	public void setPosts(List<Post> posts) {
		this.posts = posts;
	}


	public void setConfig(Config config) {
		this.config = config;
	}


	public String toString() {
		String lastPost = this.lastPost != null ? " last changed on "
		    + SimpleDateFormat.getDateTimeInstance().format(this.lastPost) : "";
		return "Topic '" + name + "'" + lastPost + " started by " + topicStarter + " (" + url
		    + ") ";
	}


	public String toStringFormatted() {
		StringBuilder builder = new StringBuilder();
		builder.append(toString() + "\n");
		builder.append("With " + posts.size() + " posts.\n");
		builder.append(LINE);
		for (Post post : posts) {
			builder.append(post.toStringFormatted());
			builder.append('\n');
		}
		return builder.toString();
	}


	public Topic clone() {
		try {
			return (Topic) super.clone();
		} catch (CloneNotSupportedException e) {
			return null;
		}
	}


	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		result = prime * result + ((topicStarter == null) ? 0 : topicStarter.hashCode());
		return result;
	}


	/**
	 * A topic is equal if the name and the topic starter is equal.
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (getClass() != obj.getClass()) {
			return false;
		}
		Topic other = (Topic) obj;
		if (name == null) {
			if (other.name != null) {
				return false;
			}
		} else if (!name.equals(other.name)) {
			return false;
		}
		if (topicStarter == null) {
			if (other.topicStarter != null) {
				return false;
			}
		} else if (!topicStarter.equals(other.topicStarter)) {
			return false;
		}
		return true;
	}

	private final static String LINE = StringUtils.repeat("*", 100) + "\n";
}
